import unittest
import difflib
import sys
from fractions import Fraction as F

from abcesac import abc_to_esac
from abcesac.parser import ABCParser
from abcesac.music import Song

class ParseABCHeaderTestCase(unittest.TestCase):
    def setUp(self):
        self.song = Song()
        self.parser = ABCParser(self.song)

    def test_parse_headers(self):
        header = 'X: 1'
        self.parser.parse(header)
        self.assertEquals(self.song.index, 1)

    def test_parse_title(self):
        header = 'T: test 123'
        self.parser.parse(header)
        self.assertEquals(self.song.title, 'test 123')

    def test_parse_multi_title(self):
        header = 'T: test 123\nT: second line\nT: third line'
        self.parser.parse(header)
        self.assertEquals(self.song.title, 'test 123\nsecond line\nthird line')

    def test_parse_meter(self):
        header = 'M: 3/4'
        self.parser.parse(header)
        self.assertEquals(self.song.meter, (3,4))

    def test_parse_base_length(self):
        header = 'L: 1/4'
        self.parser.parse(header)
        self.assertEquals(self.song.base_length, F('1/4'))

        header = 'L: 1/8'
        self.parser.parse(header)
        self.assertEquals(self.song.base_length, F('1/8'))

    def test_parse_key(self):
        header = 'K: G'
        self.parser.parse(header)
        self.assertEquals(self.song.key, 'G')
        self.assertEquals(self.song.mode, 'major')

        header = 'K: Ebmin'
        self.parser.parse(header)
        self.assertEquals(self.song.key, 'Eb')
        self.assertEquals(self.song.mode, 'minor')


class ABC2EsACTestCase(unittest.TestCase):
    def test_abc_to_esac(self):
        for block_idx, block in enumerate(file('data/test_songs.txt').read().split('\n\n\n')):
            abc, esac = block.split('---')
            abc = abc.strip()
            esac = esac.strip()
            try:
                result = abc_to_esac(abc)
            except Exception:
                print 'Exception while parsing block %i' % block_idx
                raise
            if result != esac:
                diff = list(difflib.Differ().compare(result.splitlines(1), esac.splitlines(1)))
                for l in diff:
                    print l.strip()
                self.fail('test failed in block %i!' % (block_idx+1))

    def test_parse_large_collection(self):
        collection = 'TESTCOL'
        output = []
        for song in file('data/irish.abc').read().split('\n\n'):
            song = song.strip()
            if song:
                abc_to_esac(song, collection=collection)

if __name__ == '__main__':
    unittest.main()


